package com.gcloud.controller.storage.driver;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gcloud.common.util.StringUtils;
import com.gcloud.common.util.SystemUtil;
import com.gcloud.controller.log.util.LongTaskUtil;
import com.gcloud.controller.storage.dao.SnapshotDao;
import com.gcloud.controller.storage.dao.VolumeDao;
import com.gcloud.controller.storage.entity.Snapshot;
import com.gcloud.controller.storage.entity.StoragePool;
import com.gcloud.controller.storage.entity.Volume;
import com.gcloud.controller.storage.model.CreateDiskResponse;
import com.gcloud.controller.storage.service.IVolumeService;
import com.gcloud.core.exception.GCloudException;
import com.gcloud.header.compute.enums.StorageType;
import com.gcloud.header.log.enums.LogType;
import com.gcloud.header.storage.StorageErrorCodes;
import com.gcloud.header.storage.enums.VolumeStatus;
import com.gcloud.header.storage.model.StoragePoolInfo;
import com.gcloud.service.common.compute.uitls.DiskQemuImgUtil;
import com.gcloud.service.common.lvm.uitls.LvmUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class LvmStorageDriver implements IStorageDriver{
	@Autowired
    private SnapshotDao snapshotDao;
	
	@Autowired
    private IVolumeService volumeService;
	
	@Autowired
    private VolumeDao volumeDao;
	
	@Override
	public StorageType storageType() {
		return StorageType.CENTRAL;
	}

	@Override
	public void createStoragePool(String poolId, String poolName, String hostname, String taskId)
			throws GCloudException {
		//创建VG有3种方式，raid、分区、整个磁盘，以下将使用“分区/dev/sdb1” 和 “磁盘/dev/sdc” 创建VG，并设置PE大小为64M
		// vgcreate poolName /dev/sdb1 /dev/sdc -s 64M
		
	}

	@Override
	public void deleteStoragePool(String poolName) throws GCloudException {
		//vgdisplay -v VolGroup05
		//umount所有lv？
		// vgchange -a n VolGroup05
		//vgremove VolGroup05
		//vgscan  验证是否已经删除
		//编辑/etc/fstab，删除对应挂载信息
		
	}

	@Override
	public StoragePoolInfo getStoragePool(StoragePool pool) throws GCloudException {
		//vgdisplay -v VolGroup05
		return null;
	}

	@Override
	public CreateDiskResponse createVolume(String taskId, StoragePool pool, Volume volume) throws GCloudException {
		// lvcreate -L 2500 -n volumeName poolName
		//创建了块设备/dev/poolName/volumeName
		boolean lvCreate = LvmUtil.lvCreate(pool.getPoolName(), "volume-" + volume.getId(), volume.getSize(), "::创建块设备" + LvmUtil.getVolumePath(pool.getPoolName(), volume.getId()) + "失败");
		
        if (volume.getImageRef() == null) {
        	LvmUtil.activeLv(LvmUtil.getVolumePath(pool.getPoolName(), volume.getId()));
        	//配置数据盘的大小为100G（即云服务器里第二块盘的空间大小）
    		//qemu-img create -f qcow2 /dev/poolName/volumeName 100G
        	DiskQemuImgUtil.create(volume.getSize(), "G", LvmUtil.getVolumePath(pool.getPoolName(), volume.getId()), "qcow2");
        } else {
        	//判断镜像在节点上是否激活
        	//如果不是激活，则进行激活操作
        	LvmUtil.activeLv(LvmUtil.getImagePath(pool.getPoolName(), volume.getImageRef()));
        	
        	//qemu-img create -b /dev/poolName/imageId -f qcow2 /dev/poolName/volumeName
        	DiskQemuImgUtil.create(LvmUtil.getImagePath(pool.getPoolName(), volume.getImageRef()), LvmUtil.getVolumePath(pool.getPoolName(), volume.getId()), "qcow2");
        }
        
        this.volumeDao.updateVolumeStatus(volume.getId(), VolumeStatus.AVAILABLE);

        CreateDiskResponse response = new CreateDiskResponse();
        response.setLogType(LogType.SYNC);
        response.setDiskId(volume.getId());
        return response;
	}

	@Override
	public void deleteVolume(String taskId, StoragePool pool, Volume volume) throws GCloudException {
		//umount /dev/poolName/volumeName -- 这步需要吗？
		//lvremove /dev/poolName/volumeName
		//lvdisplay | grep "/dev/poolName/volumeName"
		LvmUtil.remove(pool.getPoolName(), "volume-" + volume.getId());
        this.volumeService.handleDeleteVolumeSuccess(volume.getId());
        
        LongTaskUtil.syncSucc(LogType.SYNC, taskId, volume.getId());
	}

	@Override
	public void resizeVolume(String taskId, StoragePool pool, Volume volume, int newSize) throws GCloudException {
		// lvextend -L +10G /dev/poolName/volumeName
		//e2fsck /dev/poolName/volumeName  [强烈建议先不加-f]  扫描文件信息 --这步需要吗？
		//resize2fs /dev/poolName/volumeName  --这步需要吗？
		
		//缩小需要以下步骤
		//umount 挂载点
		//resize2fs /dev/poolName/volumeName 2G 
		//lvreduce -L 2G /dev/poolName/volumeName
		//mount
		LvmUtil.extend(pool.getPoolName(), "volume-" + volume.getId(), newSize-volume.getSize());
		DiskQemuImgUtil.resize(getDiskPath(pool.getPoolName(), "volume-" + volume.getId()), newSize-volume.getSize());
		this.volumeService.handleResizeVolumeSuccess(volume.getId(), newSize);
        
        LongTaskUtil.syncSucc(LogType.SYNC, taskId, volume.getId());
	}

	@Override
	public void createSnapshot(StoragePool pool, String volumeRefId, Snapshot snapshot, String taskId)
			throws GCloudException {
		//lvcreate -s -l 100 -n volumeNameSnap /dev/poolName/volumeName
		//-s    关键选项，创建快照snap的意思    
	    //-l    后面跟快照包含多少个PE的数量
	    //-n    后面跟创建的快照的名字
	    //-p r  由于快照大多为只读，改选项为为修改权限位只读（r）
		
		//lvdisplay /dev/poolName/volumeNameSnap
		//LvmUtil.snap(pool.getPoolName(), "volume-" + volumeRefId, snapshot.getId());
		//改用内部快照
		DiskQemuImgUtil.snapshot(snapshot.getId(), getDiskPath(pool.getPoolName(), "volume-" + volumeRefId));
		LongTaskUtil.syncSucc(LogType.SYNC, taskId, null);
	}

	@Override
	public void deleteSnapshot(StoragePool pool, String volumeRefId, Snapshot snapshot, String taskId)
			throws GCloudException {
		// 先在所有节点上失活该lv？
		// lvremove /dev/poolName/volumeNameSnap 
		//LvmUtil.remove(pool.getPoolName(), "volume-" + volumeRefId);
		DiskQemuImgUtil.deleteSnapshot(snapshot.getId(), getDiskPath(pool.getPoolName(), "volume-" + volumeRefId));
		LongTaskUtil.syncSucc(LogType.SYNC, taskId, snapshot.getId());
	}

	@Override
	public void resetSnapshot(StoragePool pool, String volumeRefId, Snapshot snapshot, Integer size, String taskId)
			throws GCloudException {
		// lvconvert --merge /dev/poolName/volumeNameSnap
		//LvmUtil.convert(pool.getPoolName(), snapshot.getId());
		//恢复快照后，快照会被自动删除掉，程序需要将数据库中对应的快照记录删除？
		
		DiskQemuImgUtil.resetSnapshot(snapshot.getId(), getDiskPath(pool.getPoolName(), "volume-" + volumeRefId));
		LongTaskUtil.syncSucc(LogType.SYNC, taskId, snapshot.getId());
	}
	
	private String getDiskPath(String vg, String lvName) {
		return String.format("/dev/%s/%s", vg, lvName);
	}

}
